/*
 * @Author: ischen.x ischen.x@foxmail.com
 * @Date: 2025-01-03 14:51:24
 * @LastEditors: ischen.x ischen.x@foxmail.com
 * @LastEditTime: 2025-01-09 17:06:09
 * 
 * Copyright (c) 2025 by fhchengz, All Rights Reserved. 
 */
#include "tlv.h"
#include <string.h>
#include <stdio.h>

head_type tlv_head;

typedef int (*tlv_crc_t)(uint8_t *data, uint8_t len);

static tlv_crc_t tlv_crc;

int tlv_set_crc_function(tlv_crc_t tlv_fun)
{
    int ret = 0;
    if (tlv_fun != NULL){
        tlv_crc = tlv_fun;
    } else {
        ret = -1;
    }
    return ret;
}

int tlv_pack(head_type head, tag_type tag, uint8_t *value, length_type value_len, uint8_t **output_buffer, uint8_t *out_len)
{
    if (value == NULL || output_buffer == NULL) {
        return TLV_PACK_ERR_NULL;  // 检查指针是否为空
    }

    // 计算总长度
    uint8_t total_len = 3 + value_len + 1;  // head + tag + length + value + crc

    // 动态分配内存
    *output_buffer = (uint8_t*)malloc(total_len);
    if (*output_buffer == NULL) {
        return TLV_PACK_ERR_MEMORY;  // 内存分配失败
    }

    uint8_t *ptr = *output_buffer;

    // 填充头部字段
    *ptr = head; ptr++;

    // 填充标签字段
    *ptr = tag; ptr++;

    // 填充长度字段
    *ptr = value_len; ptr++;

    // 复制值数据到 buffer
    memcpy(ptr, value, value_len); ptr += value_len;

    // 计算 CRC，如果有 CRC 函数
    if (tlv_crc != NULL) {
        *ptr = tlv_crc(*output_buffer, total_len - 1);  // CRC 排除最后一个字节（CRC 字段本身）
    } else {
        *ptr = 0;  // 默认 CRC 为 0
    }

    // 设置输出数据长度
    if (out_len != NULL) {
        *out_len = total_len;
    }

    return TLV_PACK_SUCCESS;  // 成功
}


/**
* @brief  tlv_buff_init
* @param  TlvBuff_t *tlvbuff
* @return void
* @note   初始化环形缓冲区
*/
void tlv_buff_init(TlvBuff_t *tlvbuff,head_type header)
{
  //初始化相关信息
  tlvbuff->Head = 0;
  tlvbuff->Tail = 0;
  tlvbuff->Lenght = 0;
	
	tlvbuff->buf_index = 0;
	tlvbuff->expected_length = 0;
	tlvbuff->state = STATE_SEARCH_HEADER;
	
	tlvbuff->header = header;
}

/**
* @brief  write_tlv_buff
* @param  uint8_t data
* @return FLASE:环形缓冲区已满，写入失败;TRUE:写入成功
* @note   往环形缓冲区写入uint8_t类型的数据
*/
uint8_t write_tlv_buff(TlvBuff_t *tlvbuff, uint8_t data)
{
  if(tlvbuff->Lenght >= TLV_BUFF_LEN) //判断缓冲区是否已满
  {
    return TLV_BUFF_ERR;
  }
  tlvbuff->Tlv_data[tlvbuff->Tail]=data;
  tlvbuff->Tail = (tlvbuff->Tail+1)%TLV_BUFF_LEN;//防止越界非法访问
  tlvbuff->Lenght++;
  return TLV_BUFF_SUCCESS;
}

/**
* @brief  read_tlv_buff
* @param  uint8_t *rData，用于保存读取的数据
* @return FLASE:环形缓冲区没有数据，读取失败;TRUE:读取成功
* @note   从环形缓冲区读取一个u8类型的数据
*/
uint8_t read_tlv_buff(TlvBuff_t *tlvbuff, uint8_t *rData)
{
  if(tlvbuff->Lenght == 0)//判断非空
  {
    return TLV_BUFF_ERR;
  }
  *rData = tlvbuff->Tlv_data[tlvbuff->Head];//先进先出FIFO，从缓冲区头出
  tlvbuff->Head = (tlvbuff->Head+1)%TLV_BUFF_LEN;//防止越界非法访问
  tlvbuff->Lenght--;
  return TLV_BUFF_SUCCESS;
}



int tlv_parsing(TlvBuff_t *tlvbuff,uint8_t *returnbuff){
	uint8_t byte;
	if(read_tlv_buff(tlvbuff,&byte) == TLV_BUFF_SUCCESS){
			switch(tlvbuff->state) {
					case STATE_SEARCH_HEADER:
							#if FIELD_TYPE_HEAD == USE_UINT8_T
								if(tlvbuff->buf_index == 0 && byte == (tlvbuff->header & 0xff)) {
									tlvbuff->recv_buf[tlvbuff->buf_index++] = byte;
									tlvbuff->state = STATE_READ_TAG;
								}
							#elif FIELD_TYPE_HEAD == USE_UINT16_T
								if(tlvbuff->buf_index == 0 && byte == ((tlvbuff->header >> 8) & 0xff)) {
									tlvbuff->recv_buf[tlvbuff->buf_index++] = byte;
								} 
								else if(tlvbuff->buf_index == 1 && byte == (tlvbuff->header & 0xff)) {
									tlvbuff->recv_buf[tlvbuff->buf_index++] = byte;
									tlvbuff->state = STATE_READ_TAG;
								} 
							#elif FIELD_TYPE_HEAD == USE_UINT32_T
								if(tlvbuff->buf_index == 0 && byte == ((tlvbuff->header >> 24) & 0xff)) {
									tlvbuff->recv_buf[tlvbuff->buf_index++] = byte;
								}
								else if(tlvbuff->buf_index == 1 && byte == ((tlvbuff->header >> 16) & 0xff)) {
									tlvbuff->recv_buf[tlvbuff->buf_index++] = byte;
								}
								else if(tlvbuff->buf_index == 2 && byte == ((tlvbuff->header >> 8) & 0xff)) {
									tlvbuff->recv_buf[tlvbuff->buf_index++] = byte;
								} 
								else if(tlvbuff->buf_index == 3 && byte == (tlvbuff->header & 0xff)) {
									tlvbuff->recv_buf[tlvbuff->buf_index++] = byte;
									tlvbuff->state = STATE_READ_TAG;
								} 
							#else
									#error "Unsupported head type"
							#endif
							
							else {
									tlvbuff->buf_index = 0; // 重置缓冲区
							}
							break;

					case STATE_READ_TAG:
							tlvbuff->recv_buf[tlvbuff->buf_index++] = byte;
							tlvbuff->state = STATE_READ_LENGTH;
							break;

					case STATE_READ_LENGTH: {
							tlvbuff->recv_buf[tlvbuff->buf_index++] = byte;
							uint8_t value_length = byte;
							// 计算总长度：Header(2)+Tag(1)+Length(1)+Value(n)+CRC(1)
							tlvbuff->expected_length = 5 + value_length;
							tlvbuff->state = STATE_READ_DATA;
							break;
					}

					case STATE_READ_DATA:
							tlvbuff->recv_buf[tlvbuff->buf_index++] = byte;
							// 检查是否达到预期长度
							if(tlvbuff->buf_index >= tlvbuff->expected_length - 1) { // -1因为还有CRC
									tlvbuff->state = STATE_READ_CRC;
							}
							break;

					case STATE_READ_CRC:
							tlvbuff->recv_buf[tlvbuff->buf_index++] = byte;
							// ----------- 数据处理点 -----------
							// 1. 验证CRC
							
							// 2. 提取有效数据（Header+Tag+Length+Value）
									
							
							printf("%#x,%#x,%#x,%#x,%#x,%#x,%#x,%#x,%#x\r\n",tlvbuff->recv_buf[0],tlvbuff->recv_buf[1],tlvbuff->recv_buf[2],tlvbuff->recv_buf[3],tlvbuff->recv_buf[4],tlvbuff->recv_buf[5],tlvbuff->recv_buf[6],tlvbuff->recv_buf[7],tlvbuff->recv_buf[8]);
							// 3. 重置状态机
							memset(tlvbuff->recv_buf, 0, MAX_BUF_LEN);
							tlvbuff->buf_index = 0;
							tlvbuff->state = STATE_SEARCH_HEADER;
							return TLV_PACK_SUCCESS;
					}

					// 防止缓冲区溢出
					if(tlvbuff->buf_index >= MAX_BUF_LEN) {
							memset(tlvbuff->recv_buf, 0, MAX_BUF_LEN);
							tlvbuff->buf_index = 0;
							tlvbuff->state = STATE_SEARCH_HEADER;
						return TLV_PACK_ERR_BUFF;
					}
	}
	return TLV_PACK_ERR_NULL;
}
